#include <bits/stdc++.h>
using namespace std;

#define DEBUG
#ifdef DEBUG
#define TRG_PG(str, argv...) fprintf(stderr, "  TRC_PG(%s:%d):\t" str, __func__, __LINE__, ##argv)
#define debug fprintf(stderr, "DEBUG(%s:%d)\n", __func__, __LINE__)
#else
#define TRG_PG(str, argv...)
#define debug
#endif

const int MAX_N = 1e5 + 10, MAX_L = 1e6 + 10;

struct Node
{
    int d, v, a;
    int l, r;
};

Node node[MAX_N];
int n, m, L, V;

int p[MAX_N];

int q[MAX_L];
void update(int x, int u)
{
    for (;x <= L; x += (x & -x))
        q[x] += u;
}
int query(int x)
{
    int res = 0;
    for (;x > 0; x -= (x & -x))
        res += q[x];
    return res;
}

#define change(x) ((x) == int(x) ? (int)(x) - 1 : (int)(x))

bool cmp(pair<int, int> x, pair<int, int> y)
{
    return x.second < y.second;
}

void init()
{
    memset(q, 0, sizeof(q));
}

void input()
{
    cin >> n >> m >> L >> V;
    for (int i = 1; i <= n; i++)
    {
        cin >> node[i].d >> node[i].v >> node[i].a;
        if (node[i].a > 0)
        {
            int x = node[i].d + ((V * V - node[i].v * node[i].v) / (2 * node[i].a) + 1);
            if (node[i].v > V)
            {
                node[i].l = node[i].d, node[i].r = L;
            }
            else if (x <= L)
            {
                node[i].l = x, node[i].r = L;
            }
            else
            {
                node[i].l = L + 1, node[i].r = L + 1;
            }
        }
        else if (node[i].a == 0 && node[i].v > V)
        {
            node[i].l = node[i].d, node[i].r = L;
        }
        else if (node[i].a < 0 && node[i].v > V)
        {
            int x = node[i].d + change((double)(V * V - node[i].v * node[i].v) / (2 * node[i].a));
            node[i].l = node[i].d, node[i].r = min(x, L);
        }
        else
        {
            node[i].l = L + 1, node[i].r = L + 1;
        }
    }
    for (int i = 1; i <= m; i++)
    {
        cin >> p[i];
        update(p[i], 1);
    }
}

void work()
{
    vector<pair<int, int>> vec;
    int ans = 0, ans2 = m;
    for (int i = 1; i <= n; i++)
    {
        if (query(node[i].r) - query(node[i].l - 1) > 0)
        {
            ans++;
            vec.push_back({node[i].l, node[i].r});
        }
    }
    cout << ans << ' ';
    sort(vec.begin(), vec.end(), cmp);
    memset(q, 0, sizeof(q));
    for (auto &it : vec)
    {
        if (query(it.second) - query(it.first - 1) > 0)
            continue;
        int l = 1, r = m, mid, x;
        while (l <= r)
        {
            mid = (l + r) / 2;
            if (p[mid] <= it.second)
            {
                x = mid, l = mid + 1;
            }
            else
            {
                r = mid - 1;
            }
        }
        if(it.first <= p[x])
        {
            update(p[x], 1);
            ans2--;
        }
    }
    cout << ans2 << '\n';
}

int main()
{
    freopen("detect.in", "r", stdin);
    freopen("detect.out", "w", stdout);
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int T;
    cin >> T;
    while (T--)
    {
        init();
        input();
        work();
    }
    return 0;
}
